// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package app

import (
	"appengine"
	"appengine/channel"
	"appengine/taskqueue"
	"crypto/rand"
	"fmt"
	"http"
	"io/ioutil"
	"template"
	"url"
)

const backendName = "render"

// demoScene will contain the scene definition (in YAML format)
// of the default demo scene.
var demoScene string

func init() {
	http.HandleFunc("/", root)
	http.HandleFunc("/render", render)

	// Populate demoScene contents from disk.
	b, err := ioutil.ReadFile("app/scene.yaml")
	if err != nil {
		panic(err)
	}
	demoScene = string(b)
}

// rootTmpl is the front page template.
var rootTmpl = template.Must(template.ParseFile("app/root.html"))

func root(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)

	// Generate a random Channel ID so there are no collisions.
	randbits := make([]byte, 40)
	rand.Read(randbits)
	clientid := fmt.Sprintf("%x", randbits)

	// Create the channel for communicating with the client.
	token, err := channel.Create(c, clientid)
	if err != nil {
		c.Errorf("root: %v", err)
		http.Error(w, err.String(), 500)
		return
	}

	// Draw the page.
	var data = struct{ Token, ClientId, Scene string }{
		token, clientid, demoScene,
	}
	if err := rootTmpl.Execute(w, data); err != nil {
		c.Errorf("root: %v", err)
	}
}

func render(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)

	// Create a render task.
	t := taskqueue.NewPOSTTask("/task/render", url.Values{
		"scene":    {r.FormValue("scene")},
		"clientid": {r.FormValue("clientid")},
	})

	// Send the task to the backend if we're in production.
	// (There are no backends in dev.)
	if !appengine.IsDevAppServer() {
		host := backendName+"."+appengine.DefaultVersionHostname(c)
		t.Header.Set("Host", host)
	}

	// Add the task to the default queue.
	if _, err := taskqueue.Add(c, t, ""); err != nil {
		c.Errorf("add render task: %v", err)
		http.Error(w, "Error: couldn't schedule render task", 500)
		return
	}

	fmt.Fprint(w, "OK") // Say something.
}
